﻿using System;
using System.Collections.Generic;
using System.Web;
using Newtonsoft.Json;
using System.Threading;
using WebSocket.App_Code.Model;
using System.Web.SessionState;

namespace WebSocket.Socket
{
    public delegate void ProcessRequestDelegate(HttpContext ctx);
    /// <summary>
    /// Listen 的摘要说明
    /// </summary>
    public class Listen : IRequiresSessionState, IHttpAsyncHandler
    {
        static DevelopMentor.ThreadPool _threadPool;
        private static void AsyncHandler()
        {
            _threadPool = new DevelopMentor.ThreadPool(2, 25, "AsyncPool");
            _threadPool.PropogateCallContext = true;
            _threadPool.PropogateThreadPrincipal = true;
            _threadPool.PropogateHttpContext = true;
            _threadPool.Start();
        }

        void ProcessRequest(object state, DateTime requestTime)
        {
            AsyncRequestState reqState = state as AsyncRequestState;
            reqState._ctx.Server.ScriptTimeout = 1200;
            if (reqState._ctx.Request.QueryString["_type"] != null && reqState._ctx.Request.QueryString["_type"].ToString() != "")
            {
                switch (reqState._ctx.Request.QueryString["_type"].ToString())
                {
                    case "AddListen": SendListenCode(reqState._ctx); break;
                    default: break;
                }
            }
            reqState.CompleteRequest();
        }

        /// <summary>
        /// 发送标致
        /// </summary>
        /// <param name="context"></param>
        private void SendListenCode(HttpContext context)
        {
            List<string> ListenType = new List<string>();
            Users user = context.Session["User"] as Users;
            //返回的条件
            //1.有改变事件
            //2.超过120次,小于1分钟
            int WhileCount = 0;
            while (ListenType.Count == 0 && WhileCount < 100)
            {
                //判断有没有用户登陆
                if ((bool)context.Application["UserLogin_" + user.UserID.ToString()])
                {
                    ListenType.Add("UserLogin");
                    //收到通知后.改变状态
                    context.Application.Lock();
                    context.Application["UserLogin_" + user.UserID.ToString()] = false;
                    context.Application.UnLock();
                }
                //判断有没有用户退出
                if ((bool)context.Application["UserOut_" + user.UserID.ToString()])
                {
                    ListenType.Add("UserOut");
                    //收到通知后.改变状态
                    context.Application.Lock();
                    context.Application["UserOut_" + user.UserID.ToString()] = false;
                    context.Application.UnLock();
                }
                //判断有没有新的信息
                if ((bool)context.Application["NewMsg_" + user.UserID.ToString()])
                {
                    ListenType.Add("NewMsg");
                    //收到通知后.改变状态
                    context.Application.Lock();
                    context.Application["NewMsg_" + user.UserID.ToString()] = false;
                    context.Application.UnLock();
                }
                WhileCount++;
                if (ListenType.Count == 0)
                {
                    Thread.Sleep(500);
                }
            }
            string returnStr = JsonConvert.SerializeObject(ListenType);
            context.Response.Write(returnStr);
            context.Response.End();
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            AsyncRequestState reqState = new AsyncRequestState(context, cb, extraData);
            _threadPool.PostRequest(new DevelopMentor.WorkRequestDelegate(ProcessRequest), reqState);

            return reqState;
        }

        public void EndProcessRequest(IAsyncResult result)
        {
            //throw new NotImplementedException();
        }


        public void ProcessRequest(HttpContext context)
        {
            //throw new NotImplementedException();
        }
    }



    class AsyncRequestState : IAsyncResult
    {
        public AsyncRequestState(HttpContext ctx, AsyncCallback cb, object extraData)
        {
            _ctx = ctx;
            _cb = cb;
            _extraData = extraData;
        }

        internal HttpContext _ctx;
        internal AsyncCallback _cb;
        internal object _extraData;
        private bool _isCompleted = false;
        private ManualResetEvent _callCompleteEvent = null;

        internal void CompleteRequest()
        {
            _isCompleted = true;
            lock (this)
            {
                if (_callCompleteEvent != null)
                    _callCompleteEvent.Set();
            }
            // if a callback was registered, invoke it now
            if (_cb != null)
                _cb(this);
        }

        // IAsyncResult
        //
        public object AsyncState { get { return (_extraData); } }
        public bool CompletedSynchronously { get { return (false); } }
        public bool IsCompleted { get { return (_isCompleted); } }
        public WaitHandle AsyncWaitHandle
        {
            get
            {
                lock (this)
                {
                    if (_callCompleteEvent == null)
                        _callCompleteEvent = new ManualResetEvent(false);

                    return _callCompleteEvent;
                }
            }
        }
    }
}